Skip to content

♻️ 新 UI 重写:shadcn/ui + Tailwind v4 + React 19 全面重构表现层#1514

Draft
CodFrm wants to merge 169 commits into
release/v1.4-agentfrom
develop/new-ui
Draft

♻️ 新 UI 重写:shadcn/ui + Tailwind v4 + React 19 全面重构表现层#1514
CodFrm wants to merge 169 commits into
release/v1.4-agentfrom
develop/new-ui

Conversation

@CodFrm

@CodFrm CodFrm commented Jun 17, 2026

Copy link
Copy Markdown
Member

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试(单元测试已覆盖,真机可视化验收进行中)

设计稿.pen.zip

Description / 描述

🚧 草稿 PR:整个新 UI 重写的集成 PR,合并目标为 main。目前仍在做各页面的真机可视化验收,完成后再转为正式 PR。

使用 shadcn/ui + Tailwind CSS v4 + React 19src/pages/ 表现层进行从零重写,替换原有的 Arco Design + UnoCSS 技术栈。设计系统(颜色令牌、组件、布局/动效/状态规范)统一沉淀在 docs/DESIGN.md,所有页面同时适配亮色/暗色主题(Tailwind dark: 变体 + src/index.css 设计令牌)。

已完成页面

核心管理页

  • 脚本列表(ScriptList,含表格/卡片、过滤侧栏、批量操作、移动端)
  • 订阅列表(SubscribeList)
  • 脚本编辑器(ScriptEditor,Monaco + 多标签 + 代码/资源/设置/存储面板)
  • 日志(Logger)、设置(Setting)、工具(Tools)
  • 弹出层(popup)

独立页面

  • 安装页(install,身份→权限→代码 信任优先布局,脚本/订阅/Skill 安装、本地文件监听、移动端)
  • 数据导入页(import,数据导入/备份恢复)
  • 授权确认页(confirm,时长选择 + 允许/拒绝)
  • 批量更新页(batchupdate,表格勾选 + 风险标签 + 已忽略分组)

Agent 套件(7 页)

  • 会话(AgentChat,三栏可折叠 + 流式 + thinking/工具调用/任务列表/ask_user/附件富块 + 移动导航抽屉)
  • 模型服务(AgentProvider)、Skills、MCP、定时任务(AgentTasks)、OPFS 文件浏览器、设置(AgentSettings)

其它

  • i18n:7 种语言(zh-CN / zh-TW / en-US / ja-JP / de-DE / ru-RU / vi-VN)同步更新
  • 测试:遵循 TDD,使用 vitest + Testing Library,新页面均有单元/组件测试覆盖
  • 文档:新增 docs/DESIGN.md,更新 docs/DEVELOP.md / docs/README.md 等贡献者文档

待办(转正式 PR 前)

  • 各页面真机可视化验收(亮色/暗色 + 桌面/移动)
  • 页内功能与旧版逐项对账复核

Screenshots / 截图

CodFrm added 30 commits April 6, 2026 00:14
移除基于 Arco Design + UnoCSS 的旧 UI 层与相关依赖,为下一版
基于 Tailwind CSS + shadcn/ui 的 UI 重构做准备。

- 删除 6 个页面(options/popup/install/confirm/import/batchupdate)、所有 UI 组件、HTML 模板和 CSS
- 卸载 16 个 UI 相关依赖(@arco-design/web-react、unocss、@dnd-kit/*、react-dropzone、react-joyride、react-router-dom、react-icons、react-i18next、@playwright/test 等)
- 删除 e2e 测试目录与 Playwright 配置
- 更新 rspack.config.ts 移除 UI entry 和 HtmlRspackPlugin
- 更新技术栈文档(CLAUDE.md、copilot-instructions、CONTRIBUTING)

保留:非 UI 入口(service_worker/content/inject/offscreen/sandbox)、
monaco-editor、i18next、pages/store/{global,favicons,features/script}.ts
- 使用 Tailwind CSS + shadcn/ui 重构 popup 页面
- 实现完整业务逻辑:脚本列表、启用/禁用、删除、排除、GM 菜单等
- 添加 usePopupData hook 对接 service worker 后端 API 和实时订阅
- 新增 Popconfirm 组件用于删除确认
- 配置设计系统色彩令牌(品牌蓝、状态色、暗色模式)
- 搭建 options 页面入口(骨架)
- 新增 Sidebar 组件:导航、帮助中心菜单(hover触发)、主题切换、折叠
- 使用 HashRouter 配置路由(脚本列表/订阅/日志/工具/设置/编辑器)
- 提取 GithubIcon 组件替代 popup 和 sidebar 中的 inline SVG
- i18n 使用已有翻译 key,与 release/v1.4 保持一致
- 将 translation.json 拆分为 11 个命名空间(common/agent/script/editor/settings/install/popup/logs/guide/tools/permission)
- 升级 React 18→19、i18next 23→26,引入 react-i18next
- 还原 SW 层 popup 逻辑至 v1.5(不在 SW 中处理 i18n)
- 删除 Crowdin 配置、伪语言 ach-UG 及相关文档引用
- 修复 React 19 类型兼容(useRef、cloneElement)
# Conflicts:
#	package.json
#	pnpm-lock.yaml
#	src/app/service/service_worker/gm_api/gm_api.ts
#	src/app/service/service_worker/index.ts
#	src/locales/ach-UG/translation.json
#	src/locales/de-DE/translation.json
#	src/locales/en-US/translation.json
#	src/locales/ja-JP/translation.json
#	src/locales/ru-RU/translation.json
#	src/locales/vi-VN/translation.json
#	src/locales/zh-CN/translation.json
#	src/locales/zh-TW/translation.json
#	src/pages/components/CodeEditor/index.tsx
#	src/pages/components/UserConfigPanel/index.tsx
#	src/pages/components/layout/MainLayout.tsx
#	src/pages/install/App.tsx
#	src/pages/options/index.css
#	src/pages/options/routes/Logger.tsx
#	src/pages/options/routes/Setting.tsx
#	src/pages/options/routes/script/ScriptEditor.tsx
#	src/pages/popup/App.tsx
# Conflicts:
#	CONTRIBUTING.md
#	README.md
#	docs/CONTRIBUTING_EN.md
#	docs/CONTRIBUTING_RU.md
#	docs/README_RU.md
#	docs/README_ja.md
#	docs/README_zh-CN.md
#	docs/README_zh-TW.md
#	e2e/install.spec.ts
#	e2e/popup.spec.ts
#	e2e/script-editor.spec.ts
#	e2e/script-management.spec.ts
#	e2e/settings.spec.ts
#	e2e/vscode-connect.spec.ts
#	package.json
#	playwright.config.ts
#	pnpm-lock.yaml
#	src/app/service/content/scripting.ts
#	src/app/service/service_worker/gm_api/gm_api.ts
#	src/app/service/service_worker/index.ts
#	src/index.css
#	src/locales/README.md
#	src/locales/de-DE/translation.json
#	src/locales/en-US/translation.json
#	src/locales/ja-JP/translation.json
#	src/locales/locales.ts
#	src/locales/ru-RU/translation.json
#	src/locales/vi-VN/translation.json
#	src/locales/zh-CN/translation.json
#	src/locales/zh-TW/translation.json
#	src/manifest.json
#	src/pages/components/CodeEditor/index.tsx
#	src/pages/components/ScriptMenuList/index.tsx
#	src/pages/components/layout/MainLayout.tsx
#	src/pages/components/layout/Sider.tsx
#	src/pages/components/layout/SiderGuide.tsx
#	src/pages/confirm/App.tsx
#	src/pages/install/App.tsx
#	src/pages/install/hooks.tsx
#	src/pages/install/utils.ts
#	src/pages/options.html
#	src/pages/options/routes/AgentChat/ChatArea.tsx
#	src/pages/options/routes/AgentMcp.tsx
#	src/pages/options/routes/AgentOPFS.tsx
#	src/pages/options/routes/AgentProvider.tsx
#	src/pages/options/routes/AgentSettings.tsx
#	src/pages/options/routes/AgentSkills.tsx
#	src/pages/options/routes/AgentTasks.tsx
#	src/pages/options/routes/ScriptList/components.tsx
#	src/pages/options/routes/ScriptList/index.tsx
#	src/pages/options/routes/Setting.tsx
#	src/pages/options/routes/SubscribeList.tsx
#	src/pages/options/routes/Tools.tsx
#	src/pages/options/routes/script/ScriptEditor.tsx
#	src/pages/options/routes/script/index.css
#	src/pages/popup.html
#	src/pages/popup/App.tsx
#	src/pages/template.html
#	tests/pages/options/MainLayout.test.tsx
@cyfung1031

This comment was marked as outdated.

@cyfung1031

Copy link
Copy Markdown
Collaborator

d2d2869 #0b84d8

Screenshot 2026-06-21 at 11 16 23

cyfung1031 and others added 5 commits June 21, 2026 11:31
- eslint.config.mjs:还原为更简洁的 spread + exhaustive-deps 覆盖写法,移除 reactHooksRules 映射
- sort.ts:reindexScriptList 移除身份保留优化,改为直接展开

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cyfung1031

Copy link
Copy Markdown
Collaborator

57d59ee + 9591f3f

eslint-plugin-react-hooks

  • upgrade (^5.2.0 → ^7.1.1) — v7 adds the react-compiler rule

CodeEditor forwardRef → native ref prop

  • React 19 idiomatic; enables React Compiler to see through the component

reindexScriptList immutability fix

  • mutation of state objects (entry.obj.sort = i) blocks React Compiler optimization; making it immutable is directly required

@cyfung1031

cyfung1031 commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator

776e41b

Screenshot 2026-06-21 at 15 03 53

我的CSS设计被破坏了。UX是不一样的。要退回这几行
z-8 是故意的
用margin left 什么全部都有背后用意

9e80ae2
Screenshot 2026-06-21 at 15 09 06

我先退回再看你的改动 -> 看不到有修改的原因和必要。退回了


这个改动表面上只是把折叠侧栏的定位写法从:

ml-6 -translate-x-full
hover:ml-0 hover:translate-x-0
z-8

改成:

translate-x-[calc(-100%+1.5rem)]
hover:translate-x-0
z-10

但两者在交互语义上并不完全等价。

原来的 ml-6 + -translate-x-full 设计,是通过 margin-left 先为折叠状态预留一段可见/可 hover 的触发区域,再用 translate-x-full 把面板主体移出视口。hover 时同时把 translate-xmargin-left 归零,使面板从左侧自然滑出并重新贴齐边界。

改成 translate-x-[calc(-100%+1.5rem)] 后,虽然静态视觉上同样像是“侧栏隐藏后保留一小段”,但这个保留区域变成了纯 transform 计算结果,而不是由 margin 参与布局产生。这样会改变 hover 命中区域、动画起点,以及展开时的过渡手感。

transition-all 被改成 transition-[opacity,transform] 也会造成差异。原设计中 margin-left 也是动画的一部分,因此 hover:ml-0 可以平滑参与展开过程。新写法只过渡 opacity 和 transform,等于移除了 margin 参与动画的行为。

此外,z-8 改成 z-10 也不是单纯的层级提升。折叠侧栏处于 absolute 定位,并且在 hover 时会展开。如果层级过高,可能覆盖原本应优先响应的编辑区、浮层、按钮或其它交互区域。z-8 更像是一个刻意选择的中间层级:足够让侧栏触发区可用,但又不会抢占其它更高优先级 UI 的交互。

因此,这个改动不能只按“最终位置差不多”来判断。CSS 在这里不仅决定静态位置,还决定 hover 热区、动画路径、过渡属性和堆叠层级。原写法中的 ml-6hover:ml-0transition-allz-8 都承担了具体的 UX 作用,直接替换成纯 transform 计算和更高 z-index 会改变折叠侧栏的交互行为。

cyfung1031 and others added 8 commits June 21, 2026 15:13
新增 no-i18n-default-value / no-raw-color-classname 自定义规则及 harness 测试;eslint.config 升级 ecmaVersion、react-hooks recommended-latest,将 exhaustive-deps / jsx-no-literals / no-i18n-default-value 提级为 error,禁止 @radix-ui/react-* 单包导入。按约定全量整改:补 data-slot、改用设计令牌、合并 radix-ui 导入,并同步 AGENTS/DEVELOP/copilot 文档。
@cyfung1031

Copy link
Copy Markdown
Collaborator

no-raw-color-classname 只挡灰阶? 这个 rule 名字不符合吧
改成 no-raw-grey-color-classname ?

- 恢复 data-panel.test.tsx(组件仍被 5 处引用)与 toast.test.ts 的 dismiss/promise 透传用例,断言均已对照当前实现确认
- AGENTS.md 修正 no-restricted-syntax forwardRef 作用域(实为 src/pages/**,非 ui/**),并补充 projectService 类型感知规则(no-floating-promises 等)说明
@CodFrm

CodFrm commented Jun 21, 2026

Copy link
Copy Markdown
Member Author

no-raw-color-classname 只挡灰阶? 这个 rule 名字不符合吧 改成 no-raw-grey-color-classname ?

没有啊,哪里只挡灰色了?

description: "禁止 className 使用原始颜色,应使用设计令牌",

@cyfung1031

cyfung1031 commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator

项目已经使用 React 19。当前重点是降低 Options UI 的 initial loading、控制大量 Script 与 Monaco Editor 的资源占用,并修复 Search race condition。

优先级 项目 最终确认 建议
Route-level code splitting 仍存在。options/App.tsx 仍同步 import 所有主要 routes。 使用 React.lazy + Suspense 延迟加载 ScriptEditor、Agent、Settings、Tools 等 routes。
Search race condition 已通过测试确认。旧请求晚返回时会污染当前 Search cache。 SearchFilter 内使用 request ID、keyword check 或 AbortController,禁止旧响应写入 cache。
Script list virtualization 仍存在。Table、desktop cards、mobile cards 都会渲染完整列表。 使用 @tanstack/react-virtualreact-window;先对超过一定数量的非 drag 状态启用。
Monaco Editor memory policy 仍存在。所有已打开 tabs 都常驻挂载,没有数量上限。 先进行 memory profiling,再增加 LRU live-editor limit、view state 保存和旧 Editor disposal。
Derived filtering state 仍存在。同步 filtering 仍在 useEffect 中计算并写入 state。 使用 useMemo 计算同步 filters,只把 async keyword matches 保存在 state。
React 19 async primitives 尚未采用。Batch operations、search、save 等仍手动管理 async state。 在确认存在 UI blocking 后,逐步使用 useTransitionuseOptimisticuseActionState
Editor route preload 尚未实现。编辑链接没有 hover/focus preload。 完成 route lazy loading 后,使用 dynamic import() 预加载 Editor chunk。
React Compiler 尚未启用 production transform,但准备工作已部分完成。 保留 compiler-aware ESLint,先在纯 UI leaf components 上试用并进行 benchmark。

已解决或无需处理

项目 最终确认
React 19 ref prop 已完成。CodeEditor 已使用普通 ref prop,ESLint 也禁止新增 forwardRef
Compiler-aware lint 已完成。当前 eslint-plugin-react-hooksrecommended-latest rules 已启用。
Sort mutation purity 已解决。reindexScriptList 会建立新对象,不再直接修改原 Script。
CodePane cursor listener leak 未确认存在。虽然没有单独保存 listener disposable,但 Monaco Editor disposal 会清理其 event emitter;目前没有证据表明发生 leak。
Search effect cleanup 部分完成。现有 alive guard 能阻止旧 effect 更新 React state,但不能阻止旧响应污染共享 cache。

推荐实施顺序

  1. 修复已确认的 Search race condition。
  2. 为 Options routes 增加 React.lazy + Suspense
  3. 增加 Editor route preload。
  4. 对大量 Script 进行 performance benchmark,并实现 virtualization。
  5. 对 Monaco Editor 进行 memory profiling,再设计 LRU memory policy。
  6. 重构 filtering state。
  7. 最后评估 React 19 async primitives 和 React Compiler。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants